﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using NClass.TestHelper;

namespace NClass.Test
{
    public abstract class BaseCodeGenerationTest
    {
        protected abstract string ActualDirectory { get;  }
        protected abstract string ExpectedDirectory { get; }
        
        protected string PrepareGenerationOutputDirectory(Resolver.Language language, string projectName)
        {
            var targetDirectory = Path.Combine(ActualDirectory, language.ToString(), projectName);

            if (Directory.Exists(targetDirectory))
            {
                var files = Directory.GetFiles(targetDirectory, "*.*", SearchOption.AllDirectories);

                foreach (var fileName in files)
                    File.Delete(fileName);

                Directory.Delete(targetDirectory, true);
            }

            return Path.Combine(ActualDirectory, language.ToString());
        }

        protected bool ValidateOutput(Resolver.Language language, string projectName, out string errorMessage)
        {
            errorMessage = string.Empty;
            var expectedDir = Path.Combine(Directory.GetCurrentDirectory(), ExpectedDirectory, language.ToString(), projectName);
            var actualDir = Path.Combine(ActualDirectory, language.ToString(), projectName);

            var missingFiles = new List<string>();
            var filesWithDifferences = new List<string>();

            if (!Directory.Exists(expectedDir))
                errorMessage = string.Format(expectedDir + "There are no expected results for the {0} version of the {1} project", language.ToString(), projectName);
            else if (!Directory.Exists(actualDir))
                errorMessage = string.Format("There are no actual results for the {0} version of the {1} project", language.ToString(), projectName);
            else
            {
                var expectedFiles = Directory.GetFiles(expectedDir, "*.*", SearchOption.AllDirectories);
                var actualFiles = Directory.GetFiles(actualDir, "*.*", SearchOption.AllDirectories).ToList();

                foreach (var fileName in expectedFiles)
                {
                    var actualFileName = fileName.Replace(expectedDir, actualDir);

                    if (actualFiles.Contains(actualFileName))
                    {
                        actualFiles.Remove(actualFileName);

                        //CRC: Added trim for blank space at end of file
                        if (!string.Equals(File.ReadAllText(fileName).Trim(),
                            File.ReadAllText(actualFileName).Trim(), System.StringComparison.CurrentCulture))
                        {
                            filesWithDifferences.Add(Path.GetFileName(fileName));
                        }
                    }
                    else
                    {
                        missingFiles.Add(Path.GetFileName(fileName));
                    }
                }

                if (missingFiles.Count > 0)
                {
                    errorMessage = string.Format("Missing Files: {0}", string.Join(",", missingFiles));
                }

                if (actualFiles.Count > 0)
                {
                    errorMessage = string.Format("{0}Extra Files: {1}",
                        string.IsNullOrWhiteSpace(errorMessage) ? string.Empty : ", ",
                        string.Join(",", actualFiles.Select(fileName => { return Path.GetFileName(fileName); })));
                }

                if (filesWithDifferences.Count > 0)
                {
                    errorMessage = string.Format("{0}Files with Differences: {1}",
                        string.IsNullOrWhiteSpace(errorMessage) ? string.Empty : ", ",
                        string.Join(",", filesWithDifferences));
                }
            }

            return string.IsNullOrWhiteSpace(errorMessage);
        }
    }
}
